package com.xiaochong.bitong.job.service;

import com.alibaba.fastjson.JSON;
import com.google.gson.reflect.TypeToken;
import com.xc.logclient.utils.LogTrace;
import com.xiaochong.bitong.job.component.RedisCacheComponent;
import com.xiaochong.bitong.job.util.ListSortUtil;
import com.xiaochong.service.common.config.redis.RedisServer;
import com.xiaochong.tir.common.data.mapper.ExchangeTransactionpairMiddleMapper;
import com.xiaochong.tir.common.data.po.CurrencyInfo;
import com.xiaochong.tir.common.data.po.ExchangeInfo;
import com.xiaochong.tir.common.data.po.ExchangeTransactionpairMiddle;
import com.xiaochong.tir.common.data.redisPo.CoinPriceVo;
import com.xiaochong.tir.common.data.redisPo.KActionTotalPo;
import com.xiaochong.tir.common.data.vo.CurrencyQuotationResultVo;
import com.xiaochong.tir.common.util.DateUtils;
import com.xiaochong.tir.common.util.RedisKeyApp;
import com.xiaochong.tir.common.util.RedisKeysUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.MathContext;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Description: java类作用描述
 * @Author: org
 * @CreateDate: 2018/8/16 14:19
 */
@Service
public class CoinPriceCountService {

    @Autowired
    private RedisCacheComponent redisCacheComponent;
    @Autowired
    private ExchangeTransactionpairMiddleMapper exchangeTransactionpairMiddleMapper;
    @Autowired
    private RedisServer redisServer;

    public void calculateCoinPrice() {
        try {
            List<CurrencyInfo> CurrencyInfoList = redisCacheComponent.getCurrencyList();
            String rediskey;
            String redisDate;
            KActionTotalPo kAction;
            CoinPriceVo  coinPriceVo = new CoinPriceVo();;
            CoinPriceVo coinPriceVoOld;
            BigDecimal currencyPrice = BigDecimal.ZERO;
            LocalDateTime time = LocalDateTime.now();
            String tmpKey;
            if (CurrencyInfoList != null && CurrencyInfoList.size() > 0) {
                String redisPriceDate = DateUtils.localDateTimeFormatString(LocalDateTime.now(),DateUtils.format_ymds);
                String currencyMi = DateUtils.localDateTimeFormatString(LocalDateTime.now(),DateUtils.format_ymdhm);
                for(CurrencyInfo currencyInfo : CurrencyInfoList){
                    //查询当前货币关联交易所
                    ExchangeTransactionpairMiddle middle = new ExchangeTransactionpairMiddle();
                    middle.setEnableFlag(true);
                    middle.setCurrencyId(currencyInfo.getId());
                    List<ExchangeTransactionpairMiddle> list = exchangeTransactionpairMiddleMapper.selectByEntityList(middle);
                    //统计交易所有效数量和价格（价格大于0，是1h内的数据），计算平均值
                    BigDecimal totalPrice = BigDecimal.ZERO;
                    BigDecimal totalPriceCny = BigDecimal.ZERO;
                    int size = 0;
                    for(ExchangeTransactionpairMiddle mm : list){
                        //获取最新价格，判断是否是有效
                        rediskey = RedisKeysUtils.API_SERVICE_K_ACTION_ALL_DATA_PRICE + "@" + mm.getExchangeId() + "@" + mm.getTransactionName();
                        redisDate = redisServer.get( rediskey );
                        if(StringUtils.isNotBlank(redisDate)){
                            kAction = JSON.parseObject(redisDate,KActionTotalPo.class);
                            if(kAction != null && StringUtils.isNotBlank(kAction.getLastOpenPrice())){
                                currencyPrice = kAction.getNewPriceUsd();
                                if(currencyPrice!=null && currencyPrice.compareTo(BigDecimal.ZERO) > 0){
                                    totalPrice = totalPrice.add(currencyPrice);
                                    totalPriceCny = totalPriceCny.add(new BigDecimal(kAction.getOpenPriceCny()));
                                    //设置价格计算时间，已最新的为准
                                    if(StringUtils.isBlank(coinPriceVo.getDatetime()) && null != kAction.getTimeLong() ){
                                        coinPriceVo.setDatetime(String.valueOf(kAction.getTimeLong()));
                                    }else if(StringUtils.isNotBlank(coinPriceVo.getDatetime()) && null != kAction.getTimeLong()){
                                        if(kAction.getTimeLong().longValue() > Long.valueOf(coinPriceVo.getDatetime()).longValue()){
                                            coinPriceVo.setDatetime(String.valueOf(kAction.getTimeLong()));
                                        }
                                    }
                                    size ++;
                                }
                            }
                        }
                    }
                    if(size > 0){
                        totalPrice = totalPrice.divide(BigDecimal.valueOf(size),12,BigDecimal.ROUND_DOWN);
                        totalPriceCny = totalPriceCny.divide(BigDecimal.valueOf(size),12,BigDecimal.ROUND_DOWN);
                    }
                    String priceRedisKey = RedisKeyApp.COIN_PRICE+currencyInfo.getCmcId();
                    String priceRedisData = redisServer.get(priceRedisKey);
                    if(StringUtils.isNotBlank(priceRedisData)){
                        coinPriceVoOld = JSON.parseObject(priceRedisData,CoinPriceVo.class);
                    }else{
                        coinPriceVoOld = new CoinPriceVo();
                    }

                    coinPriceVo.setPriceUsd(getConverCut(totalPrice.toString()).stripTrailingZeros().toPlainString());
                    coinPriceVo.setPriceCny(getConverCut(totalPriceCny.toString()).stripTrailingZeros().toPlainString());
                    coinPriceVo.setRowKey(currencyMi);
                    if(coinPriceVoOld != null && StringUtils.isNotBlank(coinPriceVoOld.getPriceCny())){
                        if(totalPriceCny.compareTo(new BigDecimal(coinPriceVoOld.getPriceCny())) > 0){
                            coinPriceVo.setChang("+");
                        }else if(totalPriceCny.compareTo(new BigDecimal(coinPriceVoOld.getPriceCny())) == 0){
                            coinPriceVo.setChang("0");
                        }else{
                            coinPriceVo.setChang("-");
                        }
                    }else{
                        coinPriceVo.setChang("0");
                    }
                    //计算24h涨幅
                    String dataRedisKey = RedisKeyApp.COIN_24H_DATA+currencyInfo.getCmcId();
                    List<CoinPriceVo>  coinPriceVoList = redisServer.getList(dataRedisKey,new TypeToken<List<CoinPriceVo>>(){}.getType());
                    if(coinPriceVoList == null){
                        coinPriceVoList = new ArrayList<>();
                    }
                    LogTrace.infoKvs("计算货币平均价格计算涨幅","redis长度",coinPriceVoList!=null?String.valueOf(coinPriceVoList.size()):"0");
                    BigDecimal priceCny24h = BigDecimal.ZERO;
                    //存在数据计算24h涨幅
                   /* if("bitcoin".equals(currencyInfo.getCmcId()) || 28 == currencyInfo.getId().intValue()){
                        System.out.println("22222");
                    }*/
                    if(coinPriceVoList.size() > 0){
                        //转成map，然后找到24h价格,计算涨幅
                        Map<String,CoinPriceVo> map = new HashMap<>();
                        for(CoinPriceVo vo : coinPriceVoList){
                            map.put(vo.getRowKey(),vo);
                        }
                        LocalDateTime timeChange = time.minusDays(1);
                        for(int i=0;i<1440;i++){
                            timeChange = timeChange.plusMinutes(1);
                            tmpKey =DateUtils.localDateTimeFormatString(timeChange,DateUtils.format_ymdhm);
                            if(map.containsKey(tmpKey)){
                                CoinPriceVo coin = map.get(tmpKey);
                                if(coin!=null && StringUtils.isNotBlank(coin.getPriceCny())){
                                    priceCny24h = new BigDecimal(getConverCut(coin.getPriceCny()).stripTrailingZeros().toPlainString());
                                    if(priceCny24h.compareTo(BigDecimal.ZERO) > 0){
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if(priceCny24h.compareTo(BigDecimal.ZERO) > 0 && totalPriceCny.compareTo(BigDecimal.ZERO) > 0){
                        BigDecimal cha = totalPriceCny.subtract(priceCny24h);
                        BigDecimal chang = cha.divide(priceCny24h,5,BigDecimal.ROUND_DOWN).multiply(BigDecimal.valueOf(100)).setScale(2,BigDecimal.ROUND_DOWN);
                        coinPriceVo.setChang24h(getConverCut(chang.toString()).stripTrailingZeros().toPlainString());
                        coinPriceVo.setPriceCny24H(getConverCut(String.valueOf(cha)).stripTrailingZeros().toPlainString());
                    }else{
                        coinPriceVo.setChang24h("0");
                        coinPriceVo.setPriceCny24H("0");
                    }
                    //如果当前分钟和上一次不一样就要保存上一次的
                    boolean insertFalg = false;
                    if(coinPriceVoOld != null && StringUtils.isNotBlank(coinPriceVoOld.getRowKey())){
                        if(currencyMi.equals(coinPriceVoOld.getRowKey())){
                            insertFalg = true;
                        }
                    }
                    if(!insertFalg && StringUtils.isNotBlank(coinPriceVoOld.getRowKey())){
                        coinPriceVoList.add(coinPriceVoOld);
                        if(coinPriceVoList.size() > 1440){
                            coinPriceVoList.remove(0);
                        }
                    }
                    // 获取24h交易额CoinPriceVo
                    String redisCacheKey =  RedisKeysUtils.CURRENCY_MARKET+currencyInfo.getCmcId();
                    String currency24Market = redisServer.get(redisCacheKey);
                    if(StringUtils.isNotBlank(currency24Market)){
                        CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( currency24Market,CurrencyQuotationResultVo.class );
                        if(currencyQuotationResultVo != null){
                        	if(currencyQuotationResultVo.getMarkRank() != null && !"".equals(currencyQuotationResultVo.getMarkRank().trim())){
                        		coinPriceVo.setRank(Integer.valueOf(currencyQuotationResultVo.getMarkRank()));
                        	}
                            coinPriceVo.setAmount24H(getConverCut(currencyQuotationResultVo.getVolume24h().toString()).stripTrailingZeros().toPlainString());
                        }else{
                            coinPriceVo.setAmount24H("0");
                        }
                    }else{
                        coinPriceVo.setAmount24H("0");
                    }
                    coinPriceVo.setSymbol(currencyInfo.getSymbol());
                    coinPriceVo.setCoinNameCn(currencyInfo.getCoinNameCn());
                    if(StringUtils.isBlank(coinPriceVo.getDatetime())){//如果时间为空，设置为当前时间
                        coinPriceVo.setDatetime(String.valueOf(new Date().getTime()));
                    }
                    redisServer.set(priceRedisKey,JSON.toJSONString(coinPriceVo));
                    if(coinPriceVoList.size() > 0){
                        redisServer.set(dataRedisKey,coinPriceVoList);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("thread计算货币平均价格计算Error",e);
        }
    }
    public static BigDecimal getConverCut(String lastPriceB) {
        BigDecimal result = new BigDecimal(0);
        result = StringUtils.isNotBlank(lastPriceB)?new BigDecimal(lastPriceB).setScale(10,BigDecimal.ROUND_DOWN):result;
        if(result.compareTo(BigDecimal.valueOf(1)) >=0){
            result = result.setScale(2,BigDecimal.ROUND_DOWN);
        }else{
            BigDecimal divisor = BigDecimal.ONE;
            MathContext mc = new MathContext(5);
            result = result.divide(divisor, mc);
        }
        return result;
    }

    public void calculateCoinMarketCapRank() {
        try {
            List<CurrencyInfo> CurrencyInfoList = redisCacheComponent.getCurrencyList();
            CoinPriceVo coinPriceVo;
            List<CurrencyQuotationResultVo> rankList = new ArrayList<>();
            if (CurrencyInfoList != null && CurrencyInfoList.size() > 0) {
                for(CurrencyInfo currencyInfo : CurrencyInfoList){
                    String redisCacheKey =  RedisKeysUtils.CURRENCY_MARKET+currencyInfo.getCmcId();
                    String currency24Market = redisServer.get(redisCacheKey);
                    if(StringUtils.isNotBlank(currency24Market)){
                        CurrencyQuotationResultVo currencyQuotationResultVo = JSON.parseObject( currency24Market,CurrencyQuotationResultVo.class );
                        if(currencyQuotationResultVo != null){
                            rankList.add(currencyQuotationResultVo);
                        }
                    }

                }
            }
            //排名
            if(rankList.size() > 0){
                ListSortUtil sortUtil=new ListSortUtil();
                sortUtil.mySort( rankList,"marketCapCny","desc" );
                for(int i=0;i<rankList.size();i++){
                    CurrencyQuotationResultVo tmp = rankList.get(i);
                    coinPriceVo = new CoinPriceVo();
                    coinPriceVo.setRank(i+1);
                    redisServer.set(RedisKeysUtils.CURRENCY_MARKET_RANK_VX_ROBOT+tmp.getCmcId(),JSON.toJSONString(coinPriceVo));
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            LogTrace.error("thread货币货币市值排行计算Error",e);
        }
    }
}
